package com.iakuil.app.common.ws;

import com.iakuil.app.common.core.constant.RedisConstant;
import com.iakuil.app.common.core.util.JsonUtils;
import com.iakuil.app.common.core.util.MapUtils;
import com.iakuil.app.common.ws.dto.UserMsg;
import com.iakuil.app.common.ws.utils.WsSessionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

/**
 * 用户私聊消息处理
 *
 * <p>当收到来自本地客户端消息时，首先判断消息接收者是否本地session。
 * <p>是则推送给接收者，不是就推送到Redis让别的节点处理。
 *
 * @author Kai
 */
@Slf4j
public class UserMessageHandler extends TextWebSocketHandler {

    private final RedisTemplate<String, Object> redisTemplate;

    public UserMessageHandler(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        long count = WsSessionUtils.join(session);
        log.info("当前WS服务器客户端连接数: [{}]", count);
        log.info("===================================");
    }

    @Override
    @SuppressWarnings("NullableProblems")
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        long count = WsSessionUtils.leave(session);
        log.info("当前WS服务器客户端连接数: [{}]", count);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        String payload = message.getPayload();
        log.info("服务端收到消息：[{}]", payload);
        UserMsg msg = JsonUtils.json2bean(payload, UserMsg.class);
        msg.setFrom(MapUtils.getStr(session.getAttributes(), RedisConstant.WS_ID_ATTR_NAME));

        String toId = msg.getTo();
        if (WsSessionUtils.contains(toId)) {
            log.info("当前WS服务器内包含客户端uid [{}]，转发此消息", toId);
            WsSessionUtils.sendMessage(toId, JsonUtils.bean2Json(msg));
        } else {
            log.info("当前WS服务器内未找到客户端uid [{}]，推送到Redis", toId);
            // 发布消息到Redis
            redisTemplate.convertAndSend(RedisConstant.WS_UNICAST_CHANNEL, msg);
        }
    }
}
